#include "Sphere.h"
#include <iostream>
using namespace std;

Vector Sphere::getNormal (const Point& p) const
{
	Vector res = Vector(location, p);
	res.normalize();
	return res;
}

bool Sphere::intersection(Ray& ray, Intersection& i) const
{
	if (!boundingBox.intersection(ray,i))
		return false;
	
	Point O = ray.getOrigin();
	Vector D = ray.getDirection();
	
	Point intersection;
	Vector normal;
	double A, B, C, t0, t1, t, delta;
	
	A = D.get_x()*D.get_x() + D.get_y()*D.get_y() + D.get_z()*D.get_z();

	B = 2 * ( 
		D.get_x() * (O.get_x() - location.get_x()) + 
		D.get_y() * (O.get_y() - location.get_y()) + 
		D.get_z() * (O.get_z() - location.get_z()));

	C = 	(O.get_x() - location.get_x()) * (O.get_x() - location.get_x()) +
		(O.get_y() - location.get_y()) * (O.get_y() - location.get_y()) +
		(O.get_z() - location.get_z()) * (O.get_z() - location.get_z()) -
		radius * radius;
		
	delta = B * B - 4 * A * C;
	if (delta >0)
	{
		t0 = (-B - sqrt(delta)) / 2;
		t1 = (-B + sqrt(delta)) / 2;
		
		if (!(t0<0.001 && t1<0.001))
		{
			if( t0<=0.001)
			{
				t=t1;
			}
			else
			{
				t=t0;
			}

            intersection = Point(O.get_x()+D.get_x()*t, O.get_y()+D.get_y()*t, O.get_z()+D.get_z()*t);
			normal = Vector((intersection.get_x()-location.get_x())/radius, (intersection.get_y()-location.get_y())/radius, (intersection.get_z()-location.get_z())/radius);
			normal.normalize();
			i.setC(color);
			i.setNormal(normal);
			i.setP(intersection);
			i.setDistance(t);
			return(true);
		}
		
	}
	return(false);
}

Sphere::Sphere(const Point &p, const double &r)
{
	location=p;
	radius=r;
	boundingBox = Box(p, r*2, r*2, r*2, 0.0, 0.0);
}

